export default {
  name: "TSlideTransition",
  props: {
    appear: Boolean,
    duration: {
      type: Number,
      default: 200
    }
  },
  methods: {
    /**
     * 动画开始
     */
    __begin(el, height, done) {
      el.style.overflowY = "hidden";
      // 如果没指定高度就不赋值
      if (height !== void 0) {
        el.style.height = `${height}px`;
      }
      el.style.transition = `height ${this.duration}ms cubic-bezier(.25, .8, .50, 1)`;
      this.done = done;
      this.animating = true;
    },
    /**
     * 动画结束
     */
    __end(el, event) {
      el.style.overflowY = null;
      el.style.height = null;
      el.style.transition = null;
      this.__cleanup();
      event !== this.lastEvent && this.$emit(event);
    },
    /**
     * 清空状态
     */
    __cleanup() {
      this.done && this.done();
      this.done = null;
      this.animating = false;

      clearTimeout(this.timer);
      clearTimeout(this.timerFallback);
      this.el !== void 0 &&
        this.el.removeEventListener("transitionend", this.animListener);
      this.animListener = null;
    }
  },
  render(h) {
    return h(
      "transition",
      {
        props: {
          css: false,
          appear: this.appear
        },
        on: {
          enter: (el, done) => {
            let pos;
            this.el = el;
            if (this.animating === true) {
              // 如果正在执行动画 hide
              this.__cleanup();
              // TODO: 这是在干啥
              // pos = el.offsetHeight === el.scrollHeight ? 0 : void 0;
            } else {
              this.lastEvent = "hide";
              // 设定初始高度
              pos = 0;
            }
            this.__begin(el, pos, done);
            // 定时，等待Vue更新Dom
            this.timer = setTimeout(
              () => {
                // 更新高度
                el.style.height = `${el.scrollHeight}px`;
                this.animListener = ev => {
                  // TODO: 如果 ？？？ 或者 绑定的el没变 则 结束动画
                  // Object(ev) !== ev ||
                  if (ev && ev.target === el) {
                    this.__end(el, "show");
                  }
                };
                // 添加 动画结束监听器 和 Fallback监听器
                // 以防 transitionend 接收失败
                el.addEventListener("transitionend", this.animListener);
                this.timerFallback = setTimeout(
                  this.animListener,
                  this.duration * 1.1
                );
              },
              this.duration ? 100 : 0
            );
          },
          leave: (el, done) => {
            let pos;
            this.el = el;
            if (this.animating === true) {
              this.__cleanup();
            } else {
              this.lastEvent = "show";
              pos = el.scrollHeight;
            }
            this.__begin(el, pos, done);
            this.timer = setTimeout(
              () => {
                el.style.height = 0;
                this.animListener = ev => {
                  // Object(ev) !== ev ||
                  if (ev && ev.target === el) {
                    this.__end(el, "hide");
                  }
                };
                el.addEventListener("transitionend", this.animListener);
                this.timerFallback = setTimeout(
                  this.animListener,
                  this.duration * 1.1
                );
              },
              this.duration ? 100 : 0
            );
          }
        }
      },
      this.$scopedSlots.default && this.$scopedSlots.default()
    );
  }
};
